package gov.nist.healthcare.testframework.communication.server;

import gov.nist.healthcare.testframework.TestFramework;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import javax.net.ServerSocketFactory;
import org.apache.log4j.Logger;

public class ServerContainer extends Thread {

    private static final Logger logger = Logger.getLogger(ServerContainer.class.getName());
    private ServerThread server;
    private final int incomingPort;
    private final boolean secure;
    private boolean listen;

    public ServerContainer(ServerThread server, int incomingPort, boolean secure) {
        this.server = server;
        this.incomingPort = incomingPort;
        this.secure = secure;
        listen = true;
    }

    @Override
    public void run() {
        listen(incomingPort, secure);
    }

    /**
     * Start up a daemon for monitoring incoming messages.
     * 
     * @param incomingPort
     *        the port number to listen on
     * @param secure
     *        a boolean set to true if the connection is secure
     */
    public void listen(int incomingPort, boolean secure) {
        ServerSocket serverSocket = null;
        // Create a server daemon
        try {
            if (!secure) {
                serverSocket = new ServerSocket(incomingPort);
            } else {
                ServerSocketFactory ssf = TestFramework.getInstance().getSSLContext().getServerSocketFactory();
                serverSocket = ssf.createServerSocket(incomingPort);
            }
            // The timeout is here to be able to close the test framework
            // gracefully
            serverSocket.setSoTimeout(5000);
            logger.info(String.format("Listening on port %d (%s connection)",
                    incomingPort, secure ? "Secure" : "Open"));
        } catch (IOException ioe) {
            System.err.println(String.format("Could not listen on port: %d.",
                    incomingPort));
            System.exit(-1);
        }
        while (listen) {
            Socket connection = null;
            try {
                connection = serverSocket.accept();
                if (server.getState() != State.NEW) {
                    server = server.restart();
                }
                server.setSocket(connection);
                server.setName(String.format("%s:%d",
                        connection.getInetAddress().getHostAddress(),
                        connection.getPort()));
                server.start();
            } catch (SocketTimeoutException ste) {
                if (!listen) {
                    break;
                }
            } catch (IOException ioe) {
                System.err.println(String.format(
                        "Could not accept connection on port: %d.",
                        incomingPort));
                System.exit(-1);
            }
        }
    }

    public void close() {
        listen = false;
    }
}
